home *** CD-ROM | disk | FTP | other *** search
Text File | 1991-11-12 | 55.0 KB | 2,751 lines |
- Newsgroups: comp.sources.misc
- From: sjg@zen.void.oz.au (Simon J. Gerraty)
- Subject: v25i049: pdksh - Public Domain Korn Shell, v4, Part03/09
- Message-ID: <1991Nov13.031054.15849@sparky.imd.sterling.com>
- X-Md4-Signature: 52c66eb39f12096edc2a8e55bd5d160e
- Date: Wed, 13 Nov 1991 03:10:54 GMT
- Approved: kent@sparky.imd.sterling.com
-
- Submitted-by: sjg@zen.void.oz.au (Simon J. Gerraty)
- Posting-number: Volume 25, Issue 49
- Archive-name: pdksh/part03
- Environment: UNIX
-
- #! /bin/sh
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # Contents: etc/profile sh/exec.c sh/vi.c
- # Wrapped by kent@sparky on Tue Nov 12 20:44:32 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- echo If this archive is complete, you will see the following message:
- echo ' "shar: End of archive 3 (of 9)."'
- if test -f 'etc/profile' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'etc/profile'\"
- else
- echo shar: Extracting \"'etc/profile'\" \(5445 characters\)
- sed "s/^X//" >'etc/profile' <<'END_OF_FILE'
- X:
- X# NAME:
- X# profile - global initialization for sh,ksh
- X#
- X# DESCRIPTION:
- X# This file is processed during login by /bin/sh
- X# and /bin/ksh. It is used to setup the default user
- X# environment. It is processed with root privs.
- X#
- X# SEE ALSO:
- X# $HOME/.profile
- X# /etc/ksh.kshrc
- X#
- X# AMENDED:
- X# 91/11/08 23:02:21 (sjg)
- X#
- X# RELEASED:
- X# 91/11/08 23:02:24 v2.7
- X#
- X# SCCSID:
- X# @(#)profile 2.7 91/11/08 23:02:21 (sjg)
- X#
- X# @(#)Copyright (c) 1991 Simon J. Gerraty
- X#
- X# This file is provided in the hope that it will
- X# be of use. There is absolutely NO WARRANTY.
- X# Permission to copy, redistribute or otherwise
- X# use this file is hereby granted provided that
- X# the above copyright notice and this notice are
- X# left intact.
- X
- Xcase "$_INIT_" in
- X*env*) ;;
- X*) # do these once
- X _INIT_="$_INIT_"env
- X export _INIT_
- X # sys_config.sh should set ARCH,OS,C,N,HOSTNAME,uname
- X # we use these in lots of scripts...
- X [ -f /etc/sys_config.sh ] && . /etc/sys_config.sh
- X
- X # pick one of the following for the default umask
- X # umask 002 # relaxed -rwxrwxr-x
- X umask 022 # cautious -rwxr-xr-x
- X # umask 027 # uptight -rwxr-x---
- X # umask 077 # paranoid -rwx------
- X # you can override the default umask
- X # for specific groups later...
- X
- X if [ -d /local ]; then
- X LOCAL=/local
- X else
- X LOCAL=/usr/local
- X fi
- X
- X # set system specific things,
- X # eg. set PATH,MANPATH
- X # override default ulimit if desired.
- X # defult ulmit is unlimited on SunOS
- X # and 4Mb for most System V
- X case $OS in
- X SunOS)
- X # On sun's /bin -> /usr/bin so leave it out!
- X PATH=.:/usr/bin:/usr/ucb:/usr/5bin
- X MANPATH=/usr/man
- X defterm=vt220
- X ;;
- X SCO-UNIX)
- X PATH=.:/bin:/usr/bin:/usr/lbin:/usr/dbin:/usr/ldbin
- X MANPATH=/usr/man
- X defterm=ansi
- X ;;
- X B.O.S.)
- X PATH=.:/bin:/usr/bin
- X if [ -d /usr/ucb ]; then
- X PATH=$PATH:/usr/ucb
- X fi
- X MANPATH=/usr/catman
- X defterm=vt220
- X SRC_COMPAT=_SYSV
- X export SRC_COMPAT
- X ;;
- X *)
- X PATH=.:/bin:/usr/bin
- X if [ -d /usr/ucb ]; then
- X PATH=$PATH:/usr/ucb
- X fi
- X MANPATH=/usr/catman
- X defterm=vt220
- X ;;
- X esac
- X if [ -d ${LOCAL}/bin ]; then
- X PATH=$PATH:${LOCAL}/bin
- X fi
- X if [ -d $HOME/bin -a "$HOME" != / ]; then
- X PATH=$PATH:$HOME/bin
- X fi
- X if [ -d ${LOCAL}/man ]; then
- X MANPATH=$MANPATH:${LOCAL}/man
- X fi
- X # make sure these are set at least once
- X LOGNAME=${LOGNAME:-`logname`}
- X USER=${USER:-$LOGNAME}
- X
- X # this is adapted from my whoami.sh
- X # we expect id to produce output like:
- X # uid=100(sjg) gid=10(staff) groups=10(staff),...
- X S='('
- X E=')'
- X GROUP=`id | cut -d= -f3 | \
- X sed -e "s;^[^${S}][^${S}]*${S}\([^${E}][^${E}]*\)${E}.*$;\1;"`
- X
- X # set some group specific defaults
- X case "$GROUP" in
- X staff) # staff deal with things that non-staff
- X # have no business looking at
- X umask 027
- X ;;
- X extern) # we put external accounts in group "extern"
- X # give them as much privacy as we can...
- X umask 077
- X ulimit 16384 # 8Mb file limit
- X TMOUT=600 # idle timeout
- X ;;
- X esac
- X
- X unset S E GROUP
- X export LOCAL TTY PATH LOGNAME USER
- X
- X TTY=`tty`
- X if [ $? -ne 0 ]; then
- X # This trick appears not to work under BOS 2.00.45
- X # so be careful of su - user in boot scripts.
- X TTY=none
- X else
- X TTY=`basename $TTY`
- X ORGANIZATION=""
- X COPYRIGHT="Copyright (c) `date +19%y` $ORGANIZATION"
- X export ORGANIZATION COPYRIGHT
- X
- X # set up some env variables
- X MAIL=/usr/spool/mail/$USER
- X MAILPATH=/usr/spool/mail/$USER:/etc/motd
- X EMACSDIR=${LOCAL}/lib/emacs
- X PAGER=${PAGER:-more}
- X export MAIL EMACSDIR MANPATH MAILPATH PAGER
- X
- X EDITOR=emacs
- X
- X PROMPT="<$LOGNAME@$HOSTNAME>$ "
- X PUBDIR=/usr/spool/uucppublic
- X export PUBDIR
- X [ -f /etc/profile.TeX ] && . /etc/profile.TeX
- X fi
- X
- X # test (and setup if we are Korn shell)
- X if [ "$RANDOM" != "$RANDOM" ]; then
- X # we are Korn shell
- X SHELL=/bin/ksh
- X ENV=${HOME%/}/.kshrc
- X PROMPT="<$LOGNAME@$HOSTNAME:!>$ "
- X export HISTSIZE HISTFILE ENV
- X CDPATH=.:$HOME
- X if [ "$TMOUT" ]; then
- X typeset -r TMOUT
- X fi
- X else
- X SHELL=/bin/sh
- X fi
- X PS1=$PROMPT
- X export SHELL PS1 EDITOR PATH PROMPT HOSTNAME CDPATH
- X
- X;;
- Xesac
- X
- X# login time initialization
- Xcase "$_INIT_" in
- X*log*) ;;
- X*) _INIT_="$_INIT_"log
- X
- X if [ $TTY != none -a "$0" != "-su" -a "$LOGNAME" = "`logname`" -a ! -f ~/.hushlogin ]
- X then
- X case $TERM in
- X network|unknown|dialup|"")
- X echo $N "Enter terminal type [$defterm]: $C" 1>&2
- X read tmpterm
- X TERM=${tmpterm:-$defterm}
- X ;;
- X esac
- X # welcome first time users
- X [ -r ${LOCAL}/etc/1stlogin.ann -a ! -f $HOME/... ] && \
- X . ${LOCAL}/etc/1stlogin.ann
- X # not all of the following are appropriate at all sites
- X # Sun's don't need to cat /etc/motd for instance
- X case "$OS" in
- X SunOS) ;;
- X SCO-UNIX)
- X [ -s /etc/motd ] && cat /etc/motd
- X [ -x /usr/bin/mail -a -s "$MAIL" ] &&
- X echo "You have mail."
- X [ -x /usr/bin/news ] && /usr/bin/news -n
- X ;;
- X *)
- X [ -s /etc/motd ] && cat /etc/motd
- X if [ -x /usr/bin/mailx ]; then
- X if mailx -e; then
- X echo "You have mail."
- X # show the the headers, this might
- X # be better done in .profile so they
- X # can override it.
- X# mailx -H
- X fi
- X fi
- X [ -x /usr/bin/news ] && /usr/bin/news -n
- X ;;
- X esac
- X [ -x /usr/games/fortune ] && /usr/games/fortune -a
- X # remind folk who turned on reply.pl to turn it off.
- X if [ -f $HOME/.forward ]; then
- X echo "Your mail is being forwarded to:"
- X cat $HOME/.forward
- X if [ -f $HOME/.recording ]; then
- X echo "Perhaps you should run \"reply.pl off\""
- X fi
- X fi
- X fi
- X unset tmpterm defterm C N
- X TERM=${TERM:-unknown}
- X export TERM TTY
- X;;
- Xesac
- X# Handle X-terminals if necessary
- X[ -f /etc/profile.X11 ] && . /etc/profile.X11
- END_OF_FILE
- if test 5445 -ne `wc -c <'etc/profile'`; then
- echo shar: \"'etc/profile'\" unpacked with wrong size!
- fi
- # end of 'etc/profile'
- fi
- if test -f 'sh/exec.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sh/exec.c'\"
- else
- echo shar: Extracting \"'sh/exec.c'\" \(14925 characters\)
- sed "s/^X//" >'sh/exec.c' <<'END_OF_FILE'
- X/*
- X * execute command tree
- X */
- X
- X#ifndef lint
- Xstatic char *RCSid = "$Id: exec.c,v 3.4 89/03/27 15:50:10 egisin Exp $";
- Xstatic char *sccs_id = "@(#)exec.c 1.3 91/11/09 15:35:22 (sjg)";
- X#endif
- X
- X#include <stddef.h>
- X#include <stdio.h>
- X#include <string.h>
- X#include <errno.h>
- X#include <signal.h>
- X#include <setjmp.h>
- X#include <unistd.h>
- X#include <fcntl.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include "sh.h"
- X#include "lex.h"
- X#include "tree.h"
- X#include "table.h"
- X
- Xstatic int comexec ARGS((struct op *t, char **vp, char **ap, int flags));
- Xstatic void iosetup ARGS((struct ioword *iop));
- Xstatic void echo ARGS((char **, char **));
- Xstatic int herein ARGS((char *name, int sub));
- X#ifdef SHARPBANG
- Xstatic void scriptexec ARGS((struct op *t, char **ap));
- X#endif
- X
- X/*
- X * execute command tree
- X */
- Xint
- Xexecute(t, flags)
- X register struct op *t;
- X Volatile int flags; /* if XEXEC don't fork */
- X{
- X int i;
- X int Volatile rv = 0;
- X int pv[2];
- X register char **ap;
- X char *s, *cp;
- X struct ioword **iowp;
- X
- X if (t == NULL)
- X return 0;
- X
- X if ((flags&XFORK) && !(flags&XEXEC) && t->type != TPIPE)
- X return exchild(t, flags); /* run in sub-process */
- X
- X newenv(E_EXEC);
- X if (trap)
- X runtraps();
- X
- X if (t->ioact != NULL || t->type == TPIPE) {
- X e.savefd = (short*) alloc(sizeofN(short, NUFILE), ATEMP);
- X for (i = 0; i < NUFILE; i++)
- X e.savefd[i] = 0; /* not redirected */
- X /* mark fd 0/1 in-use if pipeline */
- X if (flags&XPIPEI)
- X e.savefd[0] = -1;
- X if (flags&XPIPEO)
- X e.savefd[1] = -1;
- X }
- X
- X /* do redirection, to be restored in quitenv() */
- X if (t->ioact != NULL)
- X for (iowp = t->ioact; *iowp != NULL; iowp++)
- X iosetup(*iowp);
- X
- X switch(t->type) {
- X case TCOM:
- X e.type = E_TCOM;
- X rv = comexec(t, eval(t->vars, DOTILDE),
- X eval(t->args, DOBLANK|DOGLOB|DOTILDE), flags);
- X break;
- X
- X case TPAREN:
- X exstat = rv = execute(t->left, flags|XFORK);
- X break;
- X
- X case TPIPE:
- X flags |= XFORK;
- X flags &= ~XEXEC;
- X e.savefd[0] = savefd(0);
- X e.savefd[1] = savefd(1);
- X flags |= XPIPEO;
- X (void) dup2(e.savefd[0], 0); /* stdin of first */
- X while (t->type == TPIPE) {
- X openpipe(pv);
- X (void) dup2(pv[1], 1); /* stdout of curr */
- X exchild(t->left, flags);
- X (void) dup2(pv[0], 0); /* stdin of next */
- X closepipe(pv);
- X flags |= XPIPEI;
- X t = t->right;
- X }
- X flags &= ~ XPIPEO;
- X (void) dup2(e.savefd[1], 1); /* stdout of last */
- X exchild(t, flags);
- X (void) dup2(e.savefd[0], 0); /* close pipe in */
- X if (!(flags&XBGND))
- X exstat = rv = waitlast();
- X break;
- X
- X case TLIST:
- X while (t->type == TLIST) {
- X execute(t->left, 0);
- X t = t->right;
- X }
- X rv = execute(t, 0);
- X break;
- X
- X case TASYNC:
- X rv = execute(t->left, flags|XBGND|XFORK);
- X break;
- X
- X case TOR:
- X case TAND:
- X rv = execute(t->left, 0);
- X if (t->right != NULL && (rv == 0) == (t->type == TAND))
- X rv = execute(t->right, 0);
- X break;
- X
- X case TFOR:
- X e.type = E_LOOP;
- X ap = (t->vars != NULL) ?
- X eval(t->vars, DOBLANK|DOGLOB|DOTILDE) : e.loc->argv + 1;
- X while ((i = setjmp(e.jbuf)))
- X if (i == LBREAK)
- X goto Break1;
- X while (*ap != NULL) {
- X setstr(global(t->str), *ap++);
- X rv = execute(t->left, 0);
- X }
- X Break1:
- X break;
- X
- X case TWHILE:
- X case TUNTIL:
- X e.type = E_LOOP;
- X while ((i = setjmp(e.jbuf)))
- X if (i == LBREAK)
- X goto Break2;
- X while ((execute(t->left, 0) == 0) == (t->type == TWHILE))
- X rv = execute(t->right, 0);
- X Break2:
- X break;
- X
- X case TIF:
- X case TELIF:
- X if (t->right == NULL)
- X break; /* should be error */
- X rv = execute(t->left, 0) == 0 ?
- X execute(t->right->left, 0) :
- X execute(t->right->right, 0);
- X break;
- X
- X case TCASE:
- X cp = evalstr(t->str, 0);
- X for (t = t->left; t != NULL && t->type == TPAT; t = t->right)
- X for (ap = t->vars; *ap; ap++)
- X if ((s = evalstr(*ap, DOPAT)) && gmatch(cp, s))
- X goto Found;
- X break;
- X Found:
- X rv = execute(t->left, 0);
- X break;
- X
- X case TBRACE:
- X rv = execute(t->left, 0);
- X break;
- X
- X case TFUNCT:
- X rv = define(t->str, t->left);
- X break;
- X
- X case TTIME:
- X rv = timex(t, flags);
- X break;
- X
- X case TEXEC: /* an eval'd TCOM */
- X s = t->args[0];
- X ap = makenv();
- X#ifdef _MINIX /* no F_SETFD close-on-exec */
- X for (i = 10; i < 20; i++)
- X close(i);
- X#endif
- X execve(t->str, t->args, ap);
- X if (errno == ENOEXEC) {
- X char *shell;
- X#ifdef SHARPBANG
- X scriptexec(t, ap);
- X#else
- X shell = strval(global("EXECSHELL"));
- X if (shell && *shell) {
- X if ((shell = search(shell,path,1)) == NULL)
- X shell = SHELL;
- X } else {
- X shell = SHELL;
- X }
- X *t->args-- = t->str;
- X *t->args = shell;
- X execve(t->args[0], t->args, ap);
- X errorf("No shell\n");
- X#endif /* SHARPBANG */
- X }
- X errorf("%s: %s\n", s, strerror(errno));
- X }
- X
- X quitenv(); /* restores IO */
- X if (e.interactive) { /* flush stdout, shlout */
- X fflush(shf[1]);
- X fflush(shf[2]);
- X }
- X if ((flags&XEXEC))
- X exit(rv); /* exit child */
- X return rv;
- X}
- X
- X/*
- X * execute simple command
- X */
- X
- Xstatic int
- Xcomexec(t, vp, ap, flags)
- X struct op *t;
- X register char **ap, **vp;
- X int flags;
- X{
- X int i;
- X int rv = 0;
- X register char *cp;
- X register char **lastp;
- X register struct tbl *tp = NULL;
- X register struct block *l;
- X static struct op texec = {TEXEC};
- X extern int c_exec(), c_builtin();
- X
- X if (flag[FXTRACE])
- X echo(vp, ap);
- X
- X /* snag the last argument for $_ */
- X if ((lastp = ap) && *lastp) {
- X while (*++lastp)
- X ;
- X setstr(typeset("_",LOCAL,0),*--lastp);
- X }
- X
- X /* create new variable/function block */
- X l = (struct block*) alloc(sizeof(struct block), ATEMP);
- X l->next = e.loc; e.loc = l;
- X newblock();
- X
- X Doexec:
- X if ((cp = *ap) == NULL)
- X cp = ":";
- X tp = findcom(cp, flag[FHASHALL]);
- X
- X switch (tp->type) {
- X case CSHELL: /* shell built-in */
- X while (tp->val.f == c_builtin) {
- X if ((cp = *++ap) == NULL)
- X break;
- X tp = tsearch(&builtins, cp, hash(cp));
- X if (tp == NULL)
- X errorf("%s: not builtin\n", cp);
- X }
- X if (tp->val.f == c_exec) {
- X if (*++ap == NULL) {
- X e.savefd = NULL; /* don't restore redirection */
- X break;
- X }
- X flags |= XEXEC;
- X goto Doexec;
- X }
- X if ((tp->flag&TRACE))
- X e.loc = l->next; /* no local block */
- X i = (tp->flag&TRACE) ? 0 : LOCAL;
- X while (*vp != NULL)
- X (void) typeset(*vp++, i, 0);
- X rv = (*tp->val.f)(ap);
- X break;
- X
- X case CFUNC: /* function call */
- X if (!(tp->flag&ISSET))
- X errorf("%s: undefined function\n", cp);
- X l->argv = ap;
- X for (i = 0; *ap++ != NULL; i++)
- X ;
- X l->argc = i - 1;
- X resetopts();
- X while (*vp != NULL)
- X (void) typeset(*vp++, LOCAL, 0);
- X e.type = E_FUNC;
- X if (setjmp(e.jbuf))
- X rv = exstat; /* return # */
- X else
- X rv = execute(tp->val.t, 0);
- X break;
- X
- X case CEXEC: /* executable command */
- X if (!(tp->flag&ISSET)) {
- X /*
- X * mlj addition:
- X *
- X * If you specify a full path to a file
- X * (or type the name of a file in .) which
- X * doesn't have execute priv's, it used to
- X * just say "not found". Kind of annoying,
- X * particularly if you just wrote a script
- X * but forgot to say chmod 755 script.
- X *
- X * This should probably be done in eaccess(),
- X * but it works here (at least I haven't noticed
- X * changing errno here breaking something
- X * else).
- X *
- X * So, we assume that if the file exists, it
- X * doesn't have execute privs; else, it really
- X * is not found.
- X */
- X if (access(cp, 0) < 0)
- X shellf("%s: not found\n", cp);
- X else
- X shellf("%s: cannot execute\n", cp);
- X rv = 1;
- X break;
- X }
- X
- X /* set $_ to program's full path */
- X setstr(typeset("_", LOCAL|EXPORT, 0), tp->val.s);
- X while (*vp != NULL)
- X (void) typeset(*vp++, LOCAL|EXPORT, 0);
- X
- X if ((flags&XEXEC)) {
- X j_exit();
- X if (flag[FMONITOR] || !(flags&XBGND)) {
- X signal(SIGINT, SIG_DFL);
- X signal(SIGQUIT, SIG_DFL);
- X }
- X }
- X
- X /* to fork we set up a TEXEC node and call execute */
- X texec.left = t; /* for tprint */
- X texec.str = tp->val.s;
- X texec.args = ap;
- X rv = exchild(&texec, flags);
- X break;
- X }
- X if (rv != 0 && flag[FERREXIT])
- X leave(rv);
- X return (exstat = rv);
- X}
- X
- X#ifdef SHARPBANG
- Xstatic void
- Xscriptexec(tp, ap)
- X register struct op *tp;
- X register char **ap;
- X{
- X char line[LINE];
- X register char *cp;
- X register int fd, n;
- X char *shell;
- X
- X shell = strval(global("EXECSHELL"));
- X if (shell && *shell) {
- X if ((shell = search(shell,path,1)) == NULL)
- X shell = SHELL;
- X } else {
- X shell = SHELL;
- X }
- X
- X *tp->args-- = tp->str;
- X line[0] = '\0';
- X if ((fd = open(tp->str,0)) >= 0) {
- X if ((n = read(fd, line, LINE - 1)) > 0)
- X line[n] = '\0';
- X (void) close(fd);
- X }
- X if (line[0] == '#' && line[1] == '!') {
- X cp = &line[2];
- X while (*cp && (*cp == ' ' || *cp == '\t'))
- X cp++;
- X if (*cp && *cp != '\n') {
- X *tp->args = cp;
- X while (*cp && *cp != '\n' && *cp != ' ' && *cp != '\t')
- X cp++;
- X if (*cp && *cp != '\n') {
- X *cp++ = '\0';
- X while (*cp && (*cp == ' ' || *cp == '\t'))
- X cp++;
- X if (*cp && *cp != '\n') {
- X tp->args--;
- X tp->args[0] = tp->args[1];
- X tp->args[1] = cp;
- X while (*cp && *cp != '\n' &&
- X *cp != ' ' && *cp != '\t')
- X cp++;
- X }
- X }
- X *cp = '\0';
- X } else
- X *tp->args = shell;
- X } else
- X *tp->args = shell;
- X
- X (void) execve(tp->args[0], tp->args, ap);
- X errorf( "No shell\n" );
- X}
- X#endif /* SHARPBANG */
- X
- Xint
- Xshcomexec(wp)
- X register char **wp;
- X{
- X register struct tbl *tp;
- X
- X tp = tsearch(&builtins, *wp, hash(*wp));
- X if (tp == NULL)
- X errorf("%s: shcomexec botch\n", *wp);
- X return (*tp->val.f)(wp);
- X}
- X
- X/*
- X * define function
- X */
- Xint
- Xdefine(name, t)
- X char *name;
- X struct op *t;
- X{
- X register struct block *l;
- X register struct tbl *tp;
- X
- X for (l = e.loc; l != NULL; l = l->next) {
- X lastarea = &l->area;
- X tp = tsearch(&l->funs, name, hash(name));
- X if (tp != NULL && (tp->flag&DEFINED))
- X break;
- X if (l->next == NULL) {
- X tp = tenter(&l->funs, name, hash(name));
- X tp->flag = DEFINED|FUNCT;
- X tp->type = CFUNC;
- X }
- X }
- X
- X if ((tp->flag&ALLOC))
- X tfree(tp->val.t, lastarea);
- X tp->flag &= ~(ISSET|ALLOC);
- X
- X if (t == NULL) { /* undefine */
- X tdelete(tp);
- X return 0;
- X }
- X
- X tp->val.t = tcopy(t, lastarea);
- X tp->flag |= (ISSET|ALLOC);
- X
- X return 0;
- X}
- X
- X/*
- X * add builtin
- X */
- Xbuiltin(name, func)
- X char *name;
- X int (*func)();
- X{
- X register struct tbl *tp;
- X int flag = DEFINED;
- X
- X if (*name == '=') { /* sets keyword variables */
- X name++;
- X flag |= TRACE; /* command does variable assignment */
- X }
- X
- X tp = tenter(&builtins, name, hash(name));
- X tp->flag |= flag;
- X tp->type = CSHELL;
- X tp->val.f = func;
- X}
- X
- X/*
- X * find command
- X * either function, hashed command, or built-in (in that order)
- X */
- Xstruct tbl *
- Xfindcom(name, insert)
- X char *name;
- X int insert; /* insert if not found */
- X{
- X register struct block *l = e.loc;
- X unsigned int h = hash(name);
- X register struct tbl *tp = NULL;
- X static struct tbl temp;
- X
- X if (strchr(name, '/') != NULL) {
- X tp = &temp;
- X tp->type = CEXEC;
- X tp->flag = 0; /* make ~ISSET */
- X goto Search;
- X }
- X for (l = e.loc; l != NULL; l = l->next) {
- X tp = tsearch(&l->funs, name, h);
- X if (tp != NULL && (tp->flag&DEFINED))
- X break;
- X }
- X if (tp == NULL) {
- X tp = tsearch(&commands, name, h);
- X if (tp != NULL && eaccess(tp->val.s,1) != 0) {
- X if (tp->flag&ALLOC)
- X afree(tp->val.s, commands.areap);
- X tp->type = CEXEC;
- X tp->flag = DEFINED;
- X }
- X }
- X if (tp == NULL)
- X tp = tsearch(&builtins, name, h);
- X if (tp == NULL) {
- X tp = tenter(&commands, name, h);
- X tp->type = CEXEC;
- X tp->flag = DEFINED;
- X }
- X Search:
- X if (tp->type == CEXEC && !(tp->flag&ISSET)) {
- X if (!insert) {
- X tp = &temp;
- X tp->type = CEXEC;
- X tp->flag = 0; /* make ~ISSET */
- X }
- X name = search(name, path, 1);
- X if (name != NULL) {
- X tp->val.s = strsave(name,
- X (tp == &temp) ? ATEMP : APERM);
- X tp->flag |= ISSET|ALLOC;
- X }
- X }
- X return tp;
- X}
- X
- X/*
- X * flush executable commands with relative paths
- X */
- Xflushcom(all)
- X int all; /* just relative or all */
- X{
- X register struct tbl *tp;
- X
- X for (twalk(&commands); (tp = tnext()) != NULL; )
- X if ((tp->flag&ISSET) && (all || tp->val.s[0] != '/')) {
- X if ((tp->flag&ALLOC))
- X afree(tp->val.s, commands.areap);
- X tp->flag = DEFINED; /* make ~ISSET */
- X }
- X}
- X
- X/*
- X * search for command with PATH
- X */
- Xchar *
- Xsearch(name, path, mode)
- X char *name, *path;
- X int mode; /* 0: readable; 1: executable */
- X{
- X register int i;
- X register char *sp, *tp;
- X struct stat buf;
- X
- X if (strchr(name, '/'))
- X return (eaccess(name, mode) == 0) ? name : NULL;
- X
- X sp = path;
- X while (sp != NULL) {
- X tp = line;
- X for (; *sp != '\0'; tp++)
- X if ((*tp = *sp++) == ':') {
- X --sp;
- X break;
- X }
- X if (tp != line)
- X *tp++ = '/';
- X for (i = 0; (*tp++ = name[i++]) != '\0';)
- X ;
- X i = eaccess(line, mode);
- X if (i == 0 && (mode != 1 || stat(line,&buf) == 0 &&
- X (buf.st_mode & S_IFMT) == S_IFREG))
- X return line;
- X /* what should we do about EACCES? */
- X if (*sp++ == '\0')
- X sp = NULL;
- X }
- X return NULL;
- X}
- X
- X/*
- X * set up redirection, saving old fd's in e.savefd
- X */
- Xstatic void
- Xiosetup(iop)
- X register struct ioword *iop;
- X{
- X register int u = -1;
- X char *cp = iop->name;
- X extern long lseek();
- X
- X if (iop->unit == 0 || iop->unit == 1 || iop->unit == 2)
- X e.interactive = 0;
- X#if 0
- X if (e.savefd[iop->unit] != 0)
- X errorf("file descriptor %d already redirected\n", iop->unit);
- X#endif
- X e.savefd[iop->unit] = savefd(iop->unit);
- X
- X if ((iop->flag&IOTYPE) != IOHERE)
- X cp = evalstr(cp, DOTILDE);
- X
- X switch (iop->flag&IOTYPE) {
- X case IOREAD:
- X u = open(cp, 0);
- X break;
- X
- X case IOCAT:
- X if ((u = open(cp, 1)) >= 0) {
- X (void) lseek(u, (long)0, 2);
- X break;
- X }
- X /* FALLTHROUGH */
- X case IOWRITE:
- X u = creat(cp, 0666);
- X break;
- X
- X case IORDWR:
- X u = open(cp, 2);
- X break;
- X
- X case IOHERE:
- X u = herein(cp, iop->flag&IOEVAL);
- X /* cp may have wrong name */
- X break;
- X
- X case IODUP:
- X if (*cp == '-')
- X close(u = iop->unit);
- X else
- X if (digit(*cp))
- X u = *cp - '0';
- X else
- X errorf("%s: illegal >& argument\n", cp);
- X break;
- X }
- X if (u < 0)
- X errorf("%s: cannot %s\n", cp,
- X (iop->flag&IOTYPE) == IOWRITE ? "create" : "open");
- X if (u != iop->unit) {
- X (void) dup2(u, iop->unit);
- X if (iop->flag != IODUP)
- X close(u);
- X }
- X
- X fopenshf(iop->unit);
- X}
- X
- X/*
- X * open here document temp file.
- X * if unquoted here, expand here temp file into second temp file.
- X */
- Xstatic int
- Xherein(hname, sub)
- X char *hname;
- X int sub;
- X{
- X int fd;
- X FILE * Volatile f = NULL;
- X
- X f = fopen(hname, "r");
- X if (f == NULL)
- X return -1;
- X setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
- X
- X if (sub) {
- X char *cp;
- X struct source *s;
- X struct temp *h;
- X
- X newenv(E_ERRH);
- X if (setjmp(e.jbuf)) {
- X if (f != NULL)
- X fclose(f);
- X quitenv();
- X return -1; /* todo: error()? */
- X }
- X
- X /* set up yylex input from here file */
- X s = pushs(SFILE);
- X s->u.file = f;
- X source = s;
- X if (yylex(ONEWORD) != LWORD)
- X errorf("exec:herein error\n");
- X cp = evalstr(yylval.cp, 0);
- X
- X /* write expanded input to another temp file */
- X h = maketemp(ATEMP);
- X h->next = e.temps; e.temps = h;
- X if (h == NULL)
- X error();
- X f = fopen(h->name, "w+");
- X if (f == NULL)
- X error();
- X setvbuf(f, (char *)NULL, _IOFBF, BUFSIZ);
- X fputs(cp, f);
- X rewind(f);
- X
- X quitenv();
- X }
- X fd = dup(fileno(f));
- X fclose(f);
- X return fd;
- X}
- X
- Xstatic void
- Xecho(vp, ap)
- X register char **vp, **ap;
- X{
- X shellf("+");
- X while (*vp != NULL)
- X shellf(" %s", *vp++);
- X while (*ap != NULL)
- X shellf(" %s", *ap++);
- X shellf("\n");
- X}
- X
- END_OF_FILE
- if test 14925 -ne `wc -c <'sh/exec.c'`; then
- echo shar: \"'sh/exec.c'\" unpacked with wrong size!
- fi
- # end of 'sh/exec.c'
- fi
- if test -f 'sh/vi.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'sh/vi.c'\"
- else
- echo shar: Extracting \"'sh/vi.c'\" \(30485 characters\)
- sed "s/^X//" >'sh/vi.c' <<'END_OF_FILE'
- X/*
- X * vi command editing
- X * written by John Rochester (initially for nsh)
- X * bludgeoned to fit PD ksh by Larry Bouzane and Eric Gisin
- X * Further hacked (bugfixes and tweaks) by Mike Jetzer
- X */
- X
- X#include "config.h"
- X#ifdef VI
- X
- X#ifndef lint
- Xstatic char *RCSid = "$Id: vi.c,v 3.1 89/01/28 15:29:20 egisin Exp $";
- Xstatic char *sccs_id = "@(#)vi.c 1.3 91/11/09 15:35:09 (sjg)";
- X#endif
- X
- X#include <stddef.h>
- X#include <stdlib.h>
- X#include <string.h>
- X#include <stdio.h>
- X#include <unistd.h>
- X#include <signal.h>
- X#include <fcntl.h>
- X#include <ctype.h>
- X#include <errno.h>
- X#include <setjmp.h>
- X#include "sh.h"
- X#include "lex.h"
- X#include "tree.h" /* DOTILDE */
- X#include "table.h"
- X#include "expand.h"
- X#include "edit.h"
- X
- X#define CMDLEN 256
- X#define Ctrl(c) (c&0x1f)
- X#define bcopy(src, dst, len) memmove(dst, src, len)
- Xextern int histN();
- X
- Xstatic int nextstate();
- Xstatic int vi_insert();
- Xstatic int vi_cmd();
- Xstatic int domove();
- Xstatic int redo_insert();
- Xstatic yank_range();
- Xstatic int bracktype();
- Xstatic edit_prompt();
- Xstatic edit_reset();
- Xstatic int putbuf();
- Xstatic stripblanks();
- Xstatic del_range();
- Xstatic int findch();
- Xstatic int forwword();
- Xstatic int backword();
- Xstatic int endword();
- Xstatic int Forwword();
- Xstatic int Backword();
- Xstatic int Endword();
- Xstatic int grabhist();
- Xstatic int grabsearch();
- Xstatic redraw_line();
- Xstatic refresh();
- Xstatic int outofwin();
- Xstatic rewindow();
- Xstatic int newcol();
- Xstatic display();
- Xstatic ed_mov_opt();
- X
- X#define C_ 0x1
- X#define M_ 0x2
- X#define E_ 0x4
- X#define X_ 0x8
- X#define U_ 0x10
- X#define B_ 0x20
- X#define O_ 0x40
- X#define S_ 0x80
- X
- X#define isbad(c) (classify[c]&B_)
- X#define iscmd(c) (classify[c]&(M_|E_|C_|U_))
- X#define ismove(c) (classify[c]&M_)
- X#define isextend(c) (classify[c]&E_)
- X#define islong(c) (classify[c]&X_)
- X#define ismeta(c) (classify[c]&O_)
- X#define isundoable(c) (!(classify[c]&U_))
- X#define issrch(c) (classify[c]&S_)
- X
- Xchar classify[128] = {
- X B_, 0, 0, 0, 0, 0, O_, 0,
- X#if 1 /* Mike B. changes */
- X C_|M_, 0, O_, 0, O_, O_, O_, 0,
- X#else
- X C_, 0, O_, 0, O_, O_, O_, 0,
- X#endif
- X O_, 0, C_|U_, 0, 0, 0, 0, 0,
- X 0, 0, O_, 0, 0, 0, 0, 0,
- X#if 1 /* Mike B. changes */
- X C_|M_, 0, 0, C_, M_, C_, 0, 0,
- X#else
- X C_, 0, 0, C_, M_, C_, 0, 0,
- X#endif
- X 0, 0, C_, C_, M_, C_, 0, C_|S_,
- X M_, 0, 0, 0, 0, 0, 0, 0,
- X 0, 0, 0, M_, 0, 0, 0, C_|S_,
- X 0, C_, M_, C_, C_, M_, M_|X_, C_,
- X 0, C_, 0, 0, 0, 0, C_, 0,
- X C_, 0, C_, C_, M_|X_, 0, 0, M_,
- X C_, C_, 0, 0, 0, 0, M_, C_,
- X 0, C_, M_, E_, E_, M_, M_|X_, 0,
- X M_, C_, C_, C_, M_, 0, C_, 0,
- X C_, 0, C_, C_, M_|X_, C_|U_, 0, M_,
- X C_, E_, 0, 0, 0, 0, C_, 0
- X};
- X
- X#define MAXVICMD 3
- X#define SRCHLEN 40
- X
- X#define INSERT 1
- X#define REPLACE 2
- X
- X#define VNORMAL 0
- X#define VARG1 1
- X#define VEXTCMD 2
- X#define VARG2 3
- X#define VXCH 4
- X#define VFAIL 5
- X#define VCMD 6
- X#define VREDO 7
- X#define VLIT 8
- X#define VSEARCH 9
- X#define VREPLACE1CHAR 10
- X
- Xstruct edstate {
- X int winleft;
- X char *cbuf;
- X int cbufsize;
- X int linelen;
- X int cursor;
- X};
- X
- Xstatic char undocbuf[CMDLEN];
- X
- Xstatic struct edstate ebuf;
- Xstatic struct edstate undobuf = { 0, undocbuf, CMDLEN, 0, 0 };
- X
- Xstatic struct edstate *es; /* current editor state */
- Xstatic struct edstate *undo;
- X
- Xstatic char ibuf[CMDLEN]; /* input buffer */
- Xstatic int inslen; /* length of input buffer */
- Xstatic int srchlen; /* length of current search pattern */
- Xstatic char ybuf[CMDLEN]; /* yank buffer */
- Xstatic int yanklen; /* length of yank buffer */
- Xstatic int fsavecmd = ' '; /* last find command */
- Xstatic int fsavech; /* character to find */
- Xstatic char lastcmd[MAXVICMD]; /* last non-move command */
- Xstatic int lastac; /* argcnt for lastcmd */
- Xstatic int lastsearch = ' '; /* last search command */
- Xstatic char srchpat[SRCHLEN]; /* last search pattern */
- Xstatic int insert; /* non-zero in insert mode */
- Xstatic int hnum; /* position in history */
- Xstatic int hlast; /* 1 past last position in history */
- Xstatic int modified; /* buffer has been "modified" */
- Xstatic int state;
- X
- X#if 0
- Xvi_init()
- X{
- X es = (struct edstate *) malloc((unsigned) sizeof(struct edstate));
- X fsavecmd = ' ';
- X lastsearch = ' ';
- X}
- X
- Xedit_init()
- X{
- X wbuf[0] = malloc((unsigned) (x_cols - 3));
- X wbuf[1] = malloc((unsigned) (x_cols - 3));
- X}
- X#endif
- X
- Xvoid
- Xvi_reset(buf, len)
- X char *buf;
- X int len;
- X{
- X state = VNORMAL;
- X hnum = hlast = histnum(-1) + 1;
- X insert = INSERT;
- X yanklen = 0;
- X inslen = 0;
- X lastcmd[0] = 'a';
- X lastac = 1;
- X modified = 1;
- X edit_reset(buf, len);
- X}
- X
- Xint
- Xvi_hook(ch)
- X int ch;
- X{
- X static char curcmd[MAXVICMD];
- X static char locpat[SRCHLEN];
- X static int cmdlen;
- X static int argc1, argc2;
- X int i;
- X
- X if (state != VSEARCH && (ch == '\r' || ch == '\n')) {
- X x_putc('\r');
- X x_putc('\n');
- X x_flush();
- X return 1;
- X }
- X
- X switch (state) {
- X
- X case VREPLACE1CHAR:
- X curcmd[cmdlen++] = ch;
- X state = VCMD;
- X break;
- X
- X case VNORMAL:
- X if (insert != 0) {
- X if (ch == Ctrl('v')) {
- X state = VLIT;
- X ch = '^';
- X }
- X if (vi_insert(ch) != 0) {
- X x_putc(Ctrl('g'));
- X state = VNORMAL;
- X } else {
- X if (state == VLIT) {
- X es->cursor--;
- X refresh(0);
- X } else
- X refresh(insert != 0);
- X }
- X } else {
- X cmdlen = 0;
- X argc1 = 0;
- X if (ch >= '1' && ch <= '9') {
- X argc1 = ch - '0';
- X state = VARG1;
- X } else {
- X curcmd[cmdlen++] = ch;
- X state = nextstate(ch);
- X if (state == VSEARCH) {
- X save_cbuf();
- X es->cursor = 0;
- X es->linelen = 0;
- X if (ch == '/') {
- X if (putbuf("/", 1, 0) != 0) {
- X return -1;
- X }
- X } else if (putbuf("?", 1, 0) != 0)
- X return -1;
- X refresh(0);
- X }
- X }
- X }
- X break;
- X
- X case VLIT:
- X if (isbad(ch)) {
- X del_range(es->cursor, es->cursor + 1);
- X x_putc(Ctrl('g'));
- X } else
- X es->cbuf[es->cursor++] = ch;
- X refresh(1);
- X state = VNORMAL;
- X break;
- X
- X case VARG1:
- X if (isdigit(ch))
- X argc1 = argc1 * 10 + ch - '0';
- X else {
- X curcmd[cmdlen++] = ch;
- X state = nextstate(ch);
- X }
- X break;
- X
- X case VEXTCMD:
- X argc2 = 0;
- X if (ch >= '1' && ch <= '9') {
- X argc2 = ch - '0';
- X state = VARG2;
- X return 0;
- X } else {
- X curcmd[cmdlen++] = ch;
- X if (ch == curcmd[0])
- X state = VCMD;
- X else if (ismove(ch))
- X state = nextstate(ch);
- X else
- X state = VFAIL;
- X }
- X break;
- X
- X case VARG2:
- X if (isdigit(ch))
- X argc2 = argc2 * 10 + ch - '0';
- X else {
- X if (argc1 == 0)
- X argc1 = argc2;
- X else
- X argc1 *= argc2;
- X curcmd[cmdlen++] = ch;
- X if (ch == curcmd[0])
- X state = VCMD;
- X else if (ismove(ch))
- X state = nextstate(ch);
- X else
- X state = VFAIL;
- X }
- X break;
- X
- X case VXCH:
- X if (ch == Ctrl('['))
- X state = VNORMAL;
- X else {
- X curcmd[cmdlen++] = ch;
- X state = VCMD;
- X }
- X break;
- X
- X case VSEARCH:
- X switch (ch) {
- X
- X /* case Ctrl('['): */
- X case '\r':
- X case '\n':
- X locpat[srchlen] = '\0';
- X (void) strcpy(srchpat, locpat);
- X /* redraw_line(); */
- X state = VCMD;
- X break;
- X
- X case 0x7f:
- X if (srchlen == 0) {
- X restore_cbuf();
- X state = VNORMAL;
- X } else {
- X srchlen--;
- X if (locpat[srchlen] < ' ' ||
- X locpat[srchlen] == 0x7f) {
- X es->linelen--;
- X }
- X es->linelen--;
- X es->cursor = es->linelen;
- X refresh(0);
- X return 0;
- X }
- X refresh(0);
- X break;
- X
- X case Ctrl('u'):
- X srchlen = 0;
- X es->linelen = 1;
- X es->cursor = 1;
- X refresh(0);
- X return 0;
- X
- X default:
- X if (srchlen == SRCHLEN - 1)
- X x_putc(Ctrl('g'));
- X else {
- X locpat[srchlen++] = ch;
- X if (ch < ' ' || ch == 0x7f) {
- X es->cbuf[es->linelen++] = '^';
- X es->cbuf[es->linelen++] = ch ^ '@';
- X } else
- X es->cbuf[es->linelen++] = ch;
- X es->cursor = es->linelen;
- X refresh(0);
- X }
- X return 0;
- X break;
- X }
- X break;
- X }
- X switch (state) {
- X
- X case VCMD:
- X state = VNORMAL;
- X switch (vi_cmd(argc1, curcmd)) {
- X case -1:
- X x_putc(Ctrl('g'));
- X break;
- X case 0:
- X if (insert != 0)
- X inslen = 0;
- X refresh(insert != 0);
- X break;
- X case 1:
- X refresh(0);
- X x_putc('\r');
- X x_putc('\n');
- X x_flush();
- X return 1;
- X }
- X break;
- X
- X case VREDO:
- X state = VNORMAL;
- X if (argc1 != 0)
- X lastac = argc1;
- X switch (vi_cmd(lastac, lastcmd) != 0) {
- X case -1:
- X x_putc(Ctrl('g'));
- X refresh(0);
- X break;
- X case 0:
- X if (insert != 0) {
- X if (lastcmd[0] == 's' || lastcmd[0] == 'c' ||
- X lastcmd[0] == 'C') {
- X if (redo_insert(1) != 0)
- X x_putc(Ctrl('g'));
- X } else {
- X if (redo_insert(lastac) != 0)
- X x_putc(Ctrl('g'));
- X }
- X }
- X refresh(0);
- X break;
- X case 1:
- X refresh(0);
- X x_putc('\r');
- X x_putc('\n');
- X x_flush();
- X return 1;
- X }
- X break;
- X
- X case VFAIL:
- X state = VNORMAL;
- X x_putc(Ctrl('g'));
- X break;
- X }
- X return 0;
- X}
- X
- Xstatic int
- Xnextstate(ch)
- X int ch;
- X{
- X /*
- X * probably could have been done more elegantly than
- X * by creating a new state, but it works
- X */
- X if (ch == 'r')
- X return VREPLACE1CHAR;
- X else if (isextend(ch))
- X return VEXTCMD;
- X else if (issrch(ch))
- X return VSEARCH;
- X else if (islong(ch))
- X return VXCH;
- X else if (ch == '.')
- X return VREDO;
- X else if (iscmd(ch))
- X return VCMD;
- X else
- X return VFAIL;
- X}
- X
- Xstatic int
- Xvi_insert(ch)
- X int ch;
- X{
- X int tcursor;
- X
- X switch (ch) {
- X
- X case '\0':
- X return -1;
- X
- X case Ctrl('['):
- X if (lastcmd[0] == 's' || lastcmd[0] == 'c' ||
- X lastcmd[0] == 'C')
- X return redo_insert(0);
- X else
- X return redo_insert(lastac - 1);
- X
- X case 0x7f: /* delete */
- X /* tmp fix */
- X /* general fix is to get stty erase char and use that
- X */
- X case Ctrl('H'): /* delete */
- X if (es->cursor != 0) {
- X if (inslen > 0)
- X inslen--;
- X es->cursor--;
- X if (insert != REPLACE) {
- X bcopy(&es->cbuf[es->cursor+1],
- X &es->cbuf[es->cursor],
- X es->linelen - es->cursor);
- X es->linelen--;
- X }
- X }
- X break;
- X
- X case Ctrl('U'):
- X if (es->cursor != 0) {
- X inslen = 0;
- X bcopy(&es->cbuf[es->cursor], es->cbuf,
- X es->linelen - es->cursor);
- X es->linelen -= es->cursor;
- X es->cursor = 0;
- X }
- X break;
- X
- X case Ctrl('W'):
- X if (es->cursor != 0) {
- X tcursor = backword(1);
- X bcopy(&es->cbuf[es->cursor], &es->cbuf[tcursor],
- X es->linelen - es->cursor);
- X es->linelen -= es->cursor - tcursor;
- X if (inslen < es->cursor - tcursor)
- X inslen = 0;
- X else
- X inslen -= es->cursor - tcursor;
- X es->cursor = tcursor;
- X }
- X break;
- X
- X default:
- X if (es->linelen == es->cbufsize - 1)
- X return -1;
- X ibuf[inslen++] = ch;
- X if (insert == INSERT) {
- X bcopy(&es->cbuf[es->cursor], &es->cbuf[es->cursor+1],
- X es->linelen - es->cursor);
- X es->linelen++;
- X }
- X es->cbuf[es->cursor++] = ch;
- X if (insert == REPLACE && es->cursor > es->linelen)
- X es->linelen++;
- X }
- X return 0;
- X}
- X
- Xstatic int
- Xvi_cmd(argcnt, cmd)
- X int argcnt;
- X char *cmd;
- X{
- X int ncursor;
- X int cur, c1, c2, c3 = 0;
- X char pos[10];
- X struct edstate *t;
- X
- X
- X if (argcnt == 0) {
- X if (*cmd == 'G')
- X argcnt = hlast + 1;
- X else if (*cmd != '_')
- X argcnt = 1;
- X }
- X
- X if (ismove(*cmd)) {
- X if ((cur = domove(argcnt, cmd, 0)) >= 0) {
- X if (cur == es->linelen && cur != 0)
- X cur--;
- X es->cursor = cur;
- X } else
- X return -1;
- X } else {
- X if (isundoable(*cmd)) {
- X undo->winleft = es->winleft;
- X bcopy(es->cbuf, undo->cbuf, es->linelen);
- X undo->linelen = es->linelen;
- X undo->cursor = es->cursor;
- X lastac = argcnt;
- X bcopy(cmd, lastcmd, MAXVICMD);
- X }
- X switch (*cmd) {
- X
- X case Ctrl('r'):
- X redraw_line();
- X break;
- X
- X case 'a':
- X modified = 1;
- X if (es->linelen != 0)
- X es->cursor++;
- X insert = INSERT;
- X break;
- X
- X case 'A':
- X modified = 1;
- X del_range(0, 0);
- X es->cursor = es->linelen;
- X insert = INSERT;
- X break;
- X
- X case 'c':
- X case 'd':
- X case 'y':
- X if (*cmd == cmd[1]) {
- X c1 = 0;
- X c2 = es->linelen;
- X } else if (!ismove(cmd[1]))
- X return -1;
- X else {
- X if ((ncursor = domove(argcnt, &cmd[1], 1)) < 0)
- X return -1;
- X if (*cmd == 'c' &&
- X (cmd[1]=='w' || cmd[1]=='W') &&
- X !isspace(es->cbuf[es->cursor])) {
- X while (isspace(es->cbuf[--ncursor]))
- X ;
- X ncursor++;
- X }
- X if (ncursor > es->cursor) {
- X c1 = es->cursor;
- X c2 = ncursor;
- X } else {
- X c1 = ncursor;
- X c2 = es->cursor;
- X }
- X }
- X if (*cmd != 'c' && c1 != c2)
- X yank_range(c1, c2);
- X if (*cmd != 'y') {
- X del_range(c1, c2);
- X es->cursor = c1;
- X }
- X if (*cmd == 'c') {
- X modified = 1;
- X insert = INSERT;
- X }
- X break;
- X
- X case 'p':
- X modified = 1;
- X if (es->linelen != 0)
- X es->cursor++;
- X while (putbuf(ybuf, yanklen, 0) == 0 && --argcnt > 0)
- X ;
- X if (es->cursor != 0)
- X es->cursor--;
- X if (argcnt != 0)
- X return -1;
- X break;
- X
- X case 'P':
- X modified = 1;
- X while (putbuf(ybuf, yanklen, 0) == 0 && --argcnt > 0)
- X ;
- X if (es->cursor != 0)
- X es->cursor--;
- X if (argcnt != 0)
- X return -1;
- X break;
- X
- X case 'C':
- X modified = 1;
- X del_range(es->cursor, es->linelen);
- X insert = INSERT;
- X break;
- X
- X case 'D':
- X yank_range(es->cursor, es->linelen);
- X del_range(es->cursor, es->linelen);
- X if (es->cursor != 0)
- X es->cursor--;
- X break;
- X
- X case 'G':
- X if (grabhist(modified, argcnt - 1) < 0)
- X return -1;
- X else {
- X modified = 0;
- X hnum = argcnt - 1;
- X }
- X break;
- X
- X case 'i':
- X modified = 1;
- X insert = INSERT;
- X break;
- X
- X case 'I':
- X modified = 1;
- X es->cursor = 0;
- X insert = INSERT;
- X break;
- X
- X case '+':
- X case 'j':
- X if (grabhist(modified, hnum + argcnt) < 0)
- X return -1;
- X else {
- X modified = 0;
- X hnum += argcnt;
- X }
- X break;
- X
- X case '-':
- X case 'k':
- X if (grabhist(modified, hnum - argcnt) < 0)
- X return -1;
- X else {
- X modified = 0;
- X hnum -= argcnt;
- X }
- X break;
- X
- X case 'r':
- X if (es->linelen == 0)
- X return -1;
- X modified = 1;
- X es->cbuf[es->cursor] = cmd[1];
- X break;
- X
- X case 'R':
- X modified = 1;
- X insert = REPLACE;
- X break;
- X
- X case 's':
- X if (es->linelen == 0)
- X return -1;
- X modified = 1;
- X if (es->cursor + argcnt > es->linelen)
- X argcnt = es->linelen - es->cursor;
- X del_range(es->cursor, es->cursor + argcnt);
- X insert = INSERT;
- X break;
- X
- X case 'x':
- X if (es->linelen == 0)
- X return -1;
- X modified = 1;
- X if (es->cursor + argcnt > es->linelen)
- X argcnt = es->linelen - es->cursor;
- X yank_range(es->cursor, es->cursor + argcnt);
- X del_range(es->cursor, es->cursor + argcnt);
- X break;
- X
- X case 'X':
- X if (es->cursor > 0) {
- X modified = 1;
- X if (es->cursor < argcnt)
- X argcnt = es->cursor;
- X yank_range(es->cursor - argcnt, es->cursor);
- X del_range(es->cursor - argcnt, es->cursor);
- X es->cursor -= argcnt;
- X } else
- X return -1;
- X break;
- X
- X case 'u':
- X t = es;
- X es = undo;
- X undo = t;
- X break;
- X
- X case '?':
- X hnum = -1;
- X /* ahhhhhh... */
- X case '/':
- X c3 = 1;
- X srchlen = 0;
- X lastsearch = *cmd;
- X /* fall through */
- X case 'n':
- X case 'N':
- X if (lastsearch == ' ')
- X return -1;
- X if (lastsearch == '?')
- X c1 = 1;
- X else
- X c1 = 0;
- X if (*cmd == 'N')
- X c1 = !c1;
- X if ((c2 = grabsearch(modified, hnum,
- X c1, srchpat)) < 0) {
- X if (c3) {
- X restore_cbuf();
- X refresh(0);
- X }
- X return -1;
- X } else {
- X modified = 0;
- X hnum = c2;
- X }
- X break;
- X case '_': {
- X int space;
- X char *p, *sp;
- X
- X (void) histnum(-1);
- X p = *histpos();
- X#define issp(c) (isspace((c)) || (c) == '\n')
- X if (argcnt) {
- X while (*p && issp(*p))
- X p++;
- X while (*p && --argcnt) {
- X while (*p && !issp(*p))
- X p++;
- X while (*p && issp(*p))
- X p++;
- X }
- X if (!*p)
- X return -1;
- X sp = p;
- X } else {
- X sp = p;
- X space = 0;
- X while (*p) {
- X if (issp(*p))
- X space = 1;
- X else if (space) {
- X space = 0;
- X sp = p;
- X }
- X p++;
- X }
- X p = sp;
- X }
- X modified = 1;
- X if (es->linelen != 0)
- X es->cursor++;
- X while (*p && !issp(*p)) {
- X argcnt++;
- X p++;
- X }
- X if (putbuf(" ", 1, 0) != 0)
- X argcnt = -1;
- X else if (putbuf(sp, argcnt, 0) != 0)
- X argcnt = -1;
- X if (argcnt < 0) {
- X if (es->cursor != 0)
- X es->cursor--;
- X return -1;
- X }
- X insert = INSERT;
- X }
- X break;
- X
- X case '~': {
- X char *p;
- X
- X if (es->linelen == 0)
- X return -1;
- X p = &es->cbuf[es->cursor];
- X if (islower(*p)) {
- X modified = 1;
- X *p = toupper(*p);
- X } else if (isupper(*p)) {
- X modified = 1;
- X *p = tolower(*p);
- X }
- X if (es->cursor < es->linelen - 1)
- X es->cursor++;
- X }
- X break;
- X
- X case '#':
- X es->cursor = 0;
- X if (putbuf("#", 1, 0) != 0)
- X return -1;
- X return 1;
- X
- X case '*': {
- X int rval = 0;
- X int start, end;
- X char *toglob = undo->cbuf;
- X char **ap;
- X char **ap2;
- X char **globstr();
- X
- X if (isspace(es->cbuf[es->cursor]))
- X return -1;
- X start = es->cursor;
- X while (start > -1 && !isspace(es->cbuf[start]))
- X start--;
- X start++;
- X end = es->cursor;
- X while (end < es->linelen && !isspace(es->cbuf[end]))
- X end++;
- X /* use undo buffer to build word up in */
- X bcopy(&es->cbuf[start], toglob, end-start);
- X if (*toglob != '~' && toglob[end-start-1] != '*') {
- X toglob[end-start] = '*';
- X toglob[end-start+1] = '\0';
- X } else
- X toglob[end-start] = '\0';
- X ap = globstr(toglob);
- X ap2 = ap;
- X if (strcmp(ap[0], toglob) == 0 && ap[1] == (char *) 0)
- X rval = -1;
- X /* restore undo buffer that we used temporarily */
- X bcopy(es->cbuf, toglob, es->linelen);
- X if (rval < 0)
- X return rval;
- X del_range(start, end);
- X es->cursor = start;
- X while (1) {
- X if (putbuf(*ap, strlen(*ap), 0) != 0) {
- X rval = -1;
- X break;
- X }
- X if (*++ap == (char *) 0)
- X break;
- X if (putbuf(" ", 1, 0) != 0) {
- X rval = -1;
- X break;
- X }
- X }
- X#if 0
- X /*
- X * this is definitely wrong
- X */
- X for (ap = ap2; *ap; ap++)
- X free(*ap);
- X
- X free(ap2);
- X#endif
- X
- X modified = 1;
- X insert = INSERT;
- X refresh(0);
- X if (rval != 0)
- X return rval;
- X }
- X break;
- X }
- X if (insert == 0 && es->cursor != 0 && es->cursor >= es->linelen)
- X es->cursor--;
- X }
- X return 0;
- X}
- X
- Xstatic int
- Xdomove(argcnt, cmd, sub)
- X int argcnt;
- X char *cmd;
- X int sub;
- X{
- X int bcount, i = 0, t; /* = 0 kludge for gcc -W */
- X int ncursor = 0; /* = 0 kludge for gcc -W */
- X
- X switch (*cmd) {
- X
- X case 'b':
- X if (!sub && es->cursor == 0)
- X return -1;
- X ncursor = backword(argcnt);
- X break;
- X
- X case 'B':
- X if (!sub && es->cursor == 0)
- X return -1;
- X ncursor = Backword(argcnt);
- X break;
- X
- X case 'e':
- X if (!sub && es->cursor + 1 >= es->linelen)
- X return -1;
- X ncursor = endword(argcnt);
- X if (sub)
- X ncursor++;
- X break;
- X
- X case 'E':
- X if (!sub && es->cursor + 1 >= es->linelen)
- X return -1;
- X ncursor = Endword(argcnt);
- X if (sub)
- X ncursor++;
- X break;
- X
- X case 'f':
- X case 'F':
- X case 't':
- X case 'T':
- X fsavecmd = *cmd;
- X fsavech = cmd[1];
- X /* drop through */
- X
- X case ',':
- X case ';':
- X if (fsavecmd == ' ')
- X return -1;
- X i = fsavecmd == 'f' || fsavecmd == 'F';
- X t = fsavecmd > 'a';
- X if (*cmd == ',')
- X t = !t;
- X if ((ncursor = findch(fsavech, argcnt, t, i)) < 0)
- X return -1;
- X if (sub && t)
- X ncursor++;
- X break;
- X
- X case 'h':
- X /* tmp fix */
- X case Ctrl('H'):
- X if (!sub && es->cursor == 0)
- X return -1;
- X ncursor = es->cursor - argcnt;
- X if (ncursor < 0)
- X ncursor = 0;
- X break;
- X
- X case ' ':
- X case 'l':
- X if (!sub && es->cursor + 1 >= es->linelen)
- X return -1;
- X if (es->linelen != 0) {
- X ncursor = es->cursor + argcnt;
- X if (ncursor >= es->linelen)
- X ncursor = es->linelen - 1;
- X }
- X break;
- X
- X case 'w':
- X if (!sub && es->cursor + 1 >= es->linelen)
- X return -1;
- X ncursor = forwword(argcnt);
- X break;
- X
- X case 'W':
- X if (!sub && es->cursor + 1 >= es->linelen)
- X return -1;
- X ncursor = Forwword(argcnt);
- X break;
- X
- X case '0':
- X ncursor = 0;
- X break;
- X
- X case '^':
- X ncursor = 0;
- X while (ncursor < es->linelen - 1 && isspace(es->cbuf[ncursor]))
- X ncursor++;
- X break;
- X
- X case '$':
- X if (es->linelen != 0)
- X ncursor = es->linelen;
- X else
- X ncursor = 0;
- X break;
- X
- X case '%':
- X ncursor = es->cursor;
- X while (ncursor < es->linelen &&
- X (i = bracktype(es->cbuf[ncursor])) == 0)
- X ncursor++;
- X if (ncursor == es->linelen)
- X return -1;
- X bcount = 1;
- X do {
- X if (i > 0) {
- X if (++ncursor >= es->linelen)
- X return -1;
- X } else {
- X if (--ncursor < 0)
- X return -1;
- X }
- X t = bracktype(es->cbuf[ncursor]);
- X if (t == i)
- X bcount++;
- X else if (t == -i)
- X bcount--;
- X } while (bcount != 0);
- X if (sub)
- X ncursor++;
- X break;
- X
- X default:
- X return -1;
- X }
- X return ncursor;
- X}
- X
- Xstatic int
- Xredo_insert(count)
- X int count;
- X{
- X while (count-- > 0)
- X if (putbuf(ibuf, inslen, insert==REPLACE) != 0)
- X return -1;
- X if (es->cursor > 0)
- X es->cursor--;
- X insert = 0;
- X return 0;
- X}
- X
- Xstatic
- Xyank_range(a, b)
- X int a, b;
- X{
- X yanklen = b - a;
- X if (yanklen != 0)
- X bcopy(&es->cbuf[a], ybuf, yanklen);
- X}
- X
- Xstatic int
- Xbracktype(ch)
- X int ch;
- X{
- X switch (ch) {
- X
- X case '(':
- X return 1;
- X
- X case '[':
- X return 2;
- X
- X case '{':
- X return 3;
- X
- X case ')':
- X return -1;
- X
- X case ']':
- X return -2;
- X
- X case '}':
- X return -3;
- X
- X default:
- X return 0;
- X }
- X}
- X
- X/*
- X * Non user interface editor routines below here
- X */
- X
- Xstatic int cur_col; /* current column on line */
- Xstatic int pwidth; /* width of prompt */
- Xstatic int winwidth; /* width of window */
- X/*static char *wbuf[2]; /* window buffers */
- Xstatic char wbuf[2][80-3]; /* window buffers */ /* TODO */
- Xstatic int win; /* window buffer in use */
- Xstatic char morec; /* more character at right of window */
- Xstatic int lastref; /* argument to last refresh() */
- Xstatic char holdbuf[CMDLEN]; /* place to hold last edit buffer */
- Xstatic int holdlen; /* length of holdbuf */
- X
- Xsave_cbuf()
- X{
- X bcopy(es->cbuf, holdbuf, es->linelen);
- X holdlen = es->linelen;
- X holdbuf[holdlen] = '\0';
- X}
- X
- Xrestore_cbuf()
- X{
- X es->cursor = 0;
- X es->linelen = holdlen;
- X bcopy(holdbuf, es->cbuf, holdlen);
- X}
- X
- Xstatic
- Xedit_reset(buf, len)
- X char *buf;
- X int len;
- X{
- X es = &ebuf;
- X es->cbuf = buf;
- X es->cbufsize = len;
- X undo = &undobuf;
- X undo->cbufsize = len;
- X
- X es->linelen = undo->linelen = 0;
- X es->cursor = undo->cursor = 0;
- X es->winleft = undo->winleft = 0;
- X
- X cur_col = pwidth = promptlen(prompt);
- X winwidth = x_cols - pwidth - 3;
- X x_putc('\r');
- X x_flush();
- X pprompt(prompt);
- X /* docap(CLR_EOL, 0); */
- X win = 0;
- X morec = ' ';
- X lastref = 1;
- X}
- X
- Xstatic int
- Xputbuf(buf, len, repl)
- X char *buf;
- X int len;
- X int repl;
- X{
- X if (len == 0)
- X return 0;
- X if (repl) {
- X if (es->cursor + len >= es->cbufsize - 1)
- X return -1;
- X if (es->cursor + len > es->linelen)
- X es->linelen = es->cursor + len;
- X } else {
- X if (es->linelen + len >= es->cbufsize - 1)
- X return -1;
- X bcopy(&es->cbuf[es->cursor], &es->cbuf[es->cursor + len],
- X es->linelen - es->cursor);
- X es->linelen += len;
- X }
- X bcopy(buf, &es->cbuf[es->cursor], len);
- X es->cursor += len;
- X return 0;
- X}
- X
- Xstatic
- Xstripblanks()
- X{
- X int ncursor;
- X
- X ncursor = 0;
- X while (ncursor < es->linelen && isspace(es->cbuf[ncursor]))
- X ncursor++;
- X del_range(0, ncursor);
- X}
- X
- Xstatic
- Xdel_range(a, b)
- X int a, b;
- X{
- X if (es->linelen != b)
- X bcopy(&es->cbuf[b], &es->cbuf[a], es->linelen - b);
- X es->linelen -= b - a;
- X}
- X
- Xstatic int
- Xfindch(ch, cnt, forw, incl)
- X int ch;
- X int forw;
- X int incl;
- X{
- X int ncursor;
- X
- X if (es->linelen == 0)
- X return -1;
- X ncursor = es->cursor;
- X while (cnt--) {
- X do {
- X if (forw) {
- X if (++ncursor == es->linelen)
- X return -1;
- X } else {
- X if (--ncursor < 0)
- X return -1;
- X }
- X } while (es->cbuf[ncursor] != ch);
- X }
- X if (!incl) {
- X if (forw)
- X ncursor--;
- X else
- X ncursor++;
- X }
- X return ncursor;
- X}
- X
- X#define Isalnum(x) (isalnum(x) || (x == '_'))
- Xstatic int
- Xforwword(argcnt)
- X int argcnt;
- X{
- X int ncursor;
- X
- X ncursor = es->cursor;
- X while (ncursor < es->linelen && argcnt--) {
- X if (Isalnum(es->cbuf[ncursor]))
- X while (Isalnum(es->cbuf[ncursor]) &&
- X ++ncursor < es->linelen)
- X ;
- X else if (!isspace(es->cbuf[ncursor]))
- X while (!Isalnum(es->cbuf[ncursor]) &&
- X !isspace(es->cbuf[ncursor]) &&
- X ++ncursor < es->linelen)
- X ;
- X while (isspace(es->cbuf[ncursor]) && ++ncursor < es->linelen)
- X ;
- X }
- X return ncursor;
- X}
- X
- Xstatic int
- Xbackword(argcnt)
- X int argcnt;
- X{
- X int ncursor;
- X
- X ncursor = es->cursor;
- X while (ncursor > 0 && argcnt--) {
- X while (--ncursor > 0 && isspace(es->cbuf[ncursor]))
- X ;
- X if (ncursor > 0) {
- X if (Isalnum(es->cbuf[ncursor]))
- X while (--ncursor >= 0 &&
- X Isalnum(es->cbuf[ncursor]))
- X ;
- X else
- X while (--ncursor >= 0 &&
- X !Isalnum(es->cbuf[ncursor]) &&
- X !isspace(es->cbuf[ncursor]))
- X ;
- X ncursor++;
- X }
- X }
- X return ncursor;
- X}
- X
- Xstatic int
- Xendword(argcnt)
- X int argcnt;
- X{
- X int ncursor;
- X
- X ncursor = es->cursor;
- X while (ncursor < es->linelen && argcnt--) {
- X while (++ncursor < es->linelen - 1 &&
- X isspace(es->cbuf[ncursor]))
- X ;
- X if (ncursor < es->linelen - 1) {
- X if (Isalnum(es->cbuf[ncursor]))
- X while (++ncursor < es->linelen &&
- X Isalnum(es->cbuf[ncursor]))
- X ;
- X else
- X while (++ncursor < es->linelen &&
- X !Isalnum(es->cbuf[ncursor]) &&
- X !isspace(es->cbuf[ncursor]))
- X ;
- X ncursor--;
- X }
- X }
- X return ncursor;
- X}
- X
- Xstatic int
- XForwword(argcnt)
- X int argcnt;
- X{
- X int ncursor;
- X
- X ncursor = es->cursor;
- X while (ncursor < es->linelen && argcnt--) {
- X while (!isspace(es->cbuf[ncursor]) && ++ncursor < es->linelen)
- X ;
- X while (isspace(es->cbuf[ncursor]) && ++ncursor < es->linelen)
- X ;
- X }
- X return ncursor;
- X}
- X
- Xstatic int
- XBackword(argcnt)
- X int argcnt;
- X{
- X int ncursor;
- X
- X ncursor = es->cursor;
- X while (ncursor > 0 && argcnt--) {
- X while (--ncursor >= 0 && isspace(es->cbuf[ncursor]))
- X ;
- X while (ncursor >= 0 && !isspace(es->cbuf[ncursor]))
- X ncursor--;
- X ncursor++;
- X }
- X return ncursor;
- X}
- X
- Xstatic int
- XEndword(argcnt)
- X int argcnt;
- X{
- X int ncursor;
- X
- X ncursor = es->cursor;
- X while (ncursor < es->linelen - 1 && argcnt--) {
- X while (++ncursor < es->linelen - 1 &&
- X isspace(es->cbuf[ncursor]))
- X ;
- X if (ncursor < es->linelen - 1) {
- X while (++ncursor < es->linelen &&
- X !isspace(es->cbuf[ncursor]))
- X ;
- X ncursor--;
- X }
- X }
- X return ncursor;
- X}
- X
- Xstatic int
- Xgrabhist(save, n)
- X int save;
- X int n;
- X{
- X char *hptr;
- X char pos[10];
- X
- X if (n < 0 || n > hlast)
- X return -1;
- X if (n == hlast) {
- X restore_cbuf();
- X return 0;
- X }
- X (void) histnum(n);
- X if ((hptr = *histpos()) == NULL) {
- X shellf("grabhist: bad history array\n");
- X return -1;
- X }
- X if (save)
- X save_cbuf();
- X es->linelen = strlen(hptr);
- X bcopy(hptr, es->cbuf, es->linelen);
- X es->cursor = 0;
- X return 0;
- X}
- X
- Xstatic int
- Xgrabsearch(save, start, fwd, pat)
- X int save, start, fwd;
- X char *pat;
- X{
- X char *hptr;
- X
- X if ((start == 0 && fwd == 0) || (start >= hlast - 1 && fwd == 1))
- X return -1;
- X if ((hptr = findhist(start, fwd, pat)) == NULL) {
- X /* if (start != 0 && fwd && match(holdbuf, pat) >= 0) { */
- X if (start != 0 && fwd && strcmp(holdbuf, pat) >= 0) {
- X restore_cbuf();
- X return 0;
- X } else
- X return -1;
- X } else if (hptr == (char *)-1) {
- X return -1;
- X }
- X if (save)
- X save_cbuf();
- X es->linelen = strlen(hptr);
- X bcopy(hptr, es->cbuf, es->linelen);
- X es->cursor = 0;
- X return histN();
- X}
- X
- Xstatic
- Xredraw_line()
- X{
- X x_putc('\r');
- X x_putc('\n');
- X x_flush();
- X pprompt(prompt);
- X cur_col = 2;
- X morec = ' ';
- X}
- X
- Xstatic
- Xrefresh(leftside)
- X int leftside;
- X{
- X if (leftside < 0)
- X leftside = lastref;
- X else
- X lastref = leftside;
- X if (outofwin())
- X rewindow();
- X display(wbuf[1 - win], wbuf[win], leftside);
- X win = 1 - win;
- X}
- X
- Xstatic int
- Xoutofwin()
- X{
- X int cur, col;
- X
- X if (es->cursor < es->winleft)
- X return 1;
- X col = 0;
- X cur = es->winleft;
- X while (cur < es->cursor)
- X col = newcol(es->cbuf[cur++], col);
- X if (col > winwidth)
- X return 1;
- X return 0;
- X}
- X
- Xstatic
- Xrewindow()
- X{
- X register int tcur, tcol;
- X int holdcur1, holdcol1;
- X int holdcur2, holdcol2;
- X
- X holdcur1 = holdcur2 = tcur = 0;
- X holdcol1 = holdcol2 = tcol = 0;
- X while (tcur < es->cursor) {
- X if (tcol - holdcol2 > winwidth / 2) {
- X holdcur1 = holdcur2;
- X holdcol1 = holdcol2;
- X holdcur2 = tcur;
- X holdcol2 = tcol;
- X }
- X tcol = newcol(es->cbuf[tcur++], tcol);
- X }
- X while (tcol - holdcol1 > winwidth / 2)
- X holdcol1 = newcol(es->cbuf[holdcur1++], holdcol1);
- X es->winleft = holdcur1;
- X}
- X
- Xstatic int
- Xnewcol(ch, col)
- X int ch, col;
- X{
- X if (ch < ' ' || ch == 0x7f) {
- X if (ch == '\t')
- X return (col | 7) + 1;
- X else
- X return col + 2;
- X } else
- X return col + 1;
- X}
- X
- Xstatic
- Xdisplay(wb1, wb2, leftside)
- X char *wb1, *wb2;
- X int leftside;
- X{
- X char *twb1, *twb2, mc;
- X int cur, col, cnt;
- X int ncol = 0; /* set to 0 kludge for gcc -W */
- X int moreright;
- X
- X col = 0;
- X cur = es->winleft;
- X moreright = 0;
- X twb1 = wb1;
- X while (col < winwidth && cur < es->linelen) {
- X if (cur == es->cursor && leftside)
- X ncol = col + pwidth;
- X if (es->cbuf[cur] < ' ' || es->cbuf[cur] == 0x7f) {
- X if (es->cbuf[cur] == '\t') {
- X do {
- X *twb1++ = ' ';
- X } while (++col < winwidth && (col & 7) != 0);
- X } else {
- X *twb1++ = '^';
- X if (++col < winwidth) {
- X *twb1++ = es->cbuf[cur] ^ '@';
- X col++;
- X }
- X }
- X } else {
- X *twb1++ = es->cbuf[cur];
- X col++;
- X }
- X if (cur == es->cursor && !leftside)
- X ncol = col + pwidth - 1;
- X cur++;
- X }
- X if (cur == es->cursor)
- X ncol = col + pwidth;
- X if (col < winwidth) {
- X while (col < winwidth) {
- X *twb1++ = ' ';
- X col++;
- X }
- X } else
- X moreright++;
- X *twb1 = ' ';
- X
- X col = pwidth;
- X cnt = winwidth;
- X twb1 = wb1;
- X twb2 = wb2;
- X while (cnt--) {
- X if (*twb1 != *twb2) {
- X if (cur_col != col)
- X ed_mov_opt(col, wb1);
- X x_putc(*twb1);
- X cur_col++;
- X }
- X twb1++;
- X twb2++;
- X col++;
- X }
- X if (es->winleft > 0 && moreright)
- X mc = '+';
- X else if (es->winleft > 0)
- X mc = '<';
- X else if (moreright)
- X mc = '>';
- X else
- X mc = ' ';
- X if (mc != morec) {
- X ed_mov_opt(x_cols - 2, wb1);
- X x_putc(mc);
- X cur_col++;
- X morec = mc;
- X }
- X#if 0
- X /*
- X * Hack to fix teh ^r redraw problem, but it redraws way too much.
- X * Probably unacceptable at low baudrates. Someone please fix this
- X */
- X else
- X {
- X ed_mov_opt(x_cols - 2, wb1);
- X }
- X#endif
- X if (cur_col != ncol)
- X ed_mov_opt(ncol, wb1);
- X}
- X
- Xstatic
- Xed_mov_opt(col, wb)
- X int col;
- X char *wb;
- X{
- X if (col < cur_col) {
- X if (col + 1 < cur_col - col) {
- X x_putc('\r');
- X x_flush();
- X pprompt(prompt);
- X cur_col = pwidth;
- X while (cur_col++ < col)
- X x_putc(*wb++);
- X } else {
- X while (cur_col-- > col)
- X x_putc('\b');
- X }
- X } else {
- X wb = &wb[cur_col - pwidth];
- X while (cur_col++ < col)
- X x_putc(*wb++);
- X }
- X cur_col = col;
- X}
- X
- Xint
- Xx_vi(buf, len)
- X char *buf;
- X size_t len;
- X{
- X int c;
- X
- X vi_reset(buf, len > CMDLEN ? CMDLEN : len);
- X x_flush();
- X while ((c = getch()) != -1) {
- X if (vi_hook(c))
- X break;
- X x_flush();
- X }
- X
- X if (c == -1)
- X return -1;
- X
- X if (es->cbuf != buf) {
- X bcopy(es->cbuf, buf, es->linelen);
- X buf[es->linelen] = '\n';
- X } else
- X es->cbuf[es->linelen] = '\n';
- X
- X es->linelen++;
- X return es->linelen;
- X}
- X
- Xgetch()
- X{
- X char buf;
- X
- X if (read(ttyfd, &buf, 1) != 1)
- X return -1;
- X if ((buf & 0x7f) == Ctrl('c')) {
- X /*
- X * If you hit ctrl-c, the buffer was left in a
- X * strange state; the next command typed was
- X * mucked up. Doing all of this is probably
- X * overkill, but it works most of the time.
- X */
- X memset(es->cbuf, 0, CMDLEN);
- X es->winleft = 0;
- X es->cbufsize = 0;
- X es->linelen = 0;
- X es->cursor = 0;
- X
- X memset(undo->cbuf, 0, CMDLEN);
- X undo->winleft = 0;
- X undo->cbufsize = 0;
- X undo->linelen = 0;
- X undo->cursor = 0;
- X x_mode(FALSE);
- X trapsig(SIGINT);
- X } else if ((buf & 0x7f) == Ctrl('d'))
- X return -1;
- X return buf & 0x7f;
- X}
- X
- X
- Xchar **globstr(stuff)
- Xchar *stuff;
- X {
- X char *vecp[2];
- X
- X vecp[0] = stuff;
- X vecp[1] = NULL;
- X return(eval(vecp, DOBLANK|DOGLOB|DOTILDE));
- X }
- X#endif /* ifdef VI */
- END_OF_FILE
- if test 30485 -ne `wc -c <'sh/vi.c'`; then
- echo shar: \"'sh/vi.c'\" unpacked with wrong size!
- fi
- # end of 'sh/vi.c'
- fi
- echo shar: End of archive 3 \(of 9\).
- cp /dev/null ark3isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 9 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still must unpack the following archives:
- echo " " ${MISSING}
- fi
- exit 0
- exit 0 # Just in case...
- --
- Kent Landfield INTERNET: kent@sparky.IMD.Sterling.COM
- Sterling Software, IMD UUCP: uunet!sparky!kent
- Phone: (402) 291-8300 FAX: (402) 291-4362
- Please send comp.sources.misc-related mail to kent@uunet.uu.net.
-